package com.sailfish.springbootdemo.utils;

import com.sailfish.springbootdemo.pojo.Result;
import org.apache.commons.codec.Encoder;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Pattern;

public class CommonUtils {
    //1、正则表达式
    public static boolean isNumeric(String str) {
        if (str == null || "".equals(str)) {
            return false;
        }
        Pattern pattern = Pattern.compile("^[+-]?[0-9]*\\.?[0-9]+");
        return pattern.matcher(str).matches();
    }

    /**
     * 正则去除.或多余的0
     *
     * @param num 需要去除的参数
     */
    public static String removeZeros(String num) {
        if (num.indexOf(".") > 0) {
            // 去掉多余的0
            num = num.replaceAll("0+?$", "");
            // 如果最后一位是. 则去掉
            num = num.replaceAll("[.]$", "");
        }
        return num;
    }

    /**
     * 计算两个时间的年份差，保留2位小数
     */
    public static double calculateYearDifference(LocalDate date1, LocalDate date2) {
        long days = ChronoUnit.DAYS.between(date1, date2);
        double years = (double) days / 365;
        return Math.round(years * 100) / 100.0;
    }

    /**
     * 计算两个时间的天数差，保留2位小数
     */
    public static double calculateDayDifference(LocalDate date1, LocalDate date2) {
        long days = ChronoUnit.DAYS.between(date1, date2);
        return Math.round(days * 100) / 100.0;
    }

    /**
     * 获取13为时间戳
     */
    public static String getTimestamp() {
        // 获取当前时间的毫秒数
        long currentTimeMillis = System.currentTimeMillis();

        // 将毫秒数转换为13位时间戳
        String timestamp = String.valueOf(currentTimeMillis);
        while (timestamp.length() < 13) {
            timestamp = "0" + timestamp;
        }
        return timestamp;
    }

    /**
     * 判断数组中是否存在某个元素
     *
     * @param array
     * @param target
     * @return
     */
    public static boolean arrContainsTarget(String[] array, String target) {
        for (String element : array) {
            if (element.equals(target)) {
                return true;
            }
        }
        return false;
    }

    /*** 获取两个日期之间的所有月份 (年月)** @param startTime* @param endTime* @return：list*/
    public static List<String> getMonthBetweenDate(Date startTime, Date endTime) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 声明保存日期集合
        List<String> list = new ArrayList<>();

        if (startTime != null && endTime != null && startTime.before(endTime)) {
            // 转化成日期类型
            Date startDate = sdf.parse(sdf.format(startTime));
            Date endDate = sdf.parse(sdf.format(endTime));
            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把月数增加 1
                calendar.add(Calendar.MONTH, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        }
        return list;
    }

    /**
     * 计算两个时间天数
     */
    public static long getDaysBetweenTwoDate(Date startTime, Date endTime) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        Date startDate = sdf.parse(sdf.format(startTime));
        Date endDate = sdf.parse(sdf.format(endTime));
        cal1.setTime(startDate);
        cal2.setTime(endDate);
        long days = (cal2.getTimeInMillis() - cal1.getTimeInMillis()) / (1000 * 3600 * 24);
        return days;
    }

    /**
     * md5 加密
     *
     * @param str
     * @return
     */
    public static String encryptToMD5(String str) {
        return DigestUtils.md5Hex(str);
        /*// 2. 创建MD5实例
        MessageDigest md5 = MessageDigest.getInstance("MD5");

        // 3. 将字符串转换为字节数组
        byte[] inputBytes = str.getBytes();

        // 4. 计算MD5哈希值
        byte[] hashBytes = md5.digest(inputBytes);

        // 5. 将哈希值转换为字符串
        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b)); // 将每个字节转换为16进制格式的字符串
        }
        return sb.toString();*/
    }

    /**
     * 处理 excel名字过滤特殊字符
     */
    public static String handleSheetName(String sheetName) {
        sheetName = sheetName.replaceAll("[\\\\/:*?\"<>|]", ""); // 过滤特殊字符
        if(sheetName.length() > 25){
            sheetName = sheetName.substring(0, 22) + "..." + String.valueOf((Math.random() * 100000)).substring(0, 6);
        }
        return sheetName;
    }

    /**
     * 格式化当前时间
     */
    public static String formatCurrentTime() {
        // 创建日期对象
        Date date = new Date();
        // 创建SimpleDateFormat对象，并指定想要的时间格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 使用SimpleDateFormat对象格式化日期对象
        return dateFormat.format(date);
    }

    /**
     * 返回本地图片url前缀（本应写入yml，正式环境yml无该配置，开发环境直接写死）
     */
    public static String returnHostPrefixUrl() {
        return "http://192.168.31.223:8890/capacityFiles/";
    }

    /**
     * base64图片的前缀
     */
    public static String base64Prefix() {
        return "data:image/png;base64,";
    }

    /**
     * 将http图片转成base64
     */
    public static String getImageBase64FromUrl(String imageUrl) {
        String base64Image = null;
        try {
            imageUrl = imageUrl.replaceAll("\\\\", "/");
            URI uri = new URI(imageUrl);
            String encodedUrl = uri.toASCIIString();
            //System.out.println(encodedUrl);
            byte[] imageBytes = getImageDataFromUrl(encodedUrl);
            if (imageBytes != null && imageBytes.length > 0) {
                base64Image = Base64.getEncoder().encodeToString(imageBytes);
                //System.out.println("Base64 encoded image:\n" + base64Image);
            } else {
                System.err.println("Failed to retrieve the image data.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64Image;
    }

    public static byte[] getImageDataFromUrl(String urlStr) throws IOException {
        try (InputStream inputStream = new URL(urlStr).openStream()) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            int bytesRead;
            byte[] buffer = new byte[1024];

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            return outputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * get ip
     *
     * @param request
     * @return
     */
    public static String getClientIpAddress(HttpServletRequest request) {
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        return ipAddress;
    }

    /**
     * 访问一个url获取重定向后的url
     */
    public static String getFinalUrl(String shortUrl) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) new URL(shortUrl).openConnection();
        connection.setInstanceFollowRedirects(false);
        connection.connect();
        int responseCode = connection.getResponseCode();
        String finalUrl;
        if (responseCode >= 300 && responseCode < 400) {
            finalUrl = connection.getHeaderField("Location");
        } else {
            finalUrl = shortUrl;
        }
        connection.disconnect();
        return finalUrl;
    }

    /**
     * 获取url中的参数
     *
     * @param urlString
     * @return
     */
    public static Map<String, String> getURLParameters(String urlString) {
        Map<String, String> parameters = new HashMap<>();

        try {
            URL url = new URL(urlString);
            String query = url.getQuery();

            if (query != null) {
                String[] pairs = query.split("&");

                for (String pair : pairs) {
                    String[] keyValue = pair.split("=");
                    String key = URLDecoder.decode(keyValue[0], "UTF-8");
                    String value = keyValue.length > 1 ? URLDecoder.decode(keyValue[1], "UTF-8") : "";
                    parameters.put(key, value);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return parameters;
    }

    /**
     * 处理 能力值 里面 /
     */
    public static String handleZhuanyi(String value){
        if(value == null || "".equals(value)){
            return "";
        }else{
            if("/".equals(value.trim())){
                value = "";
            }
            return value;
        }
    }

    /**
     * double 类型 转 字符串  同时省略 小数点后面无用的 0
     */
    public static String formatDouble(double value) {
        // 使用正则格式化：#表示可以有，也可以没有数字，0表示一定有数字
        DecimalFormat df = new DecimalFormat("0.##");
        return df.format(value);
    }

    /**
     * 获取 接口 访问前缀
     */
    public static String getApiPrefixUrl(HttpServletRequest request) {
        // 获取协议（http 或 https）
        String scheme = request.getScheme();
        // 获取服务器名称（如 localhost）
        String serverName = request.getServerName();
        // 获取端口号
        int serverPort = request.getServerPort();
        // 获取应用上下文路径
        String contextPath = request.getContextPath();

        // 构建 URL 前缀
        StringBuilder baseUrl = new StringBuilder();
        baseUrl.append(scheme).append("://").append(serverName);
        // 如果不是默认端口，需要加上端口号
        if ((scheme.equals("http") && serverPort != 80) || (scheme.equals("https") && serverPort != 443)) {
            baseUrl.append(":").append(serverPort);
        }
        baseUrl.append(contextPath);

        return baseUrl.toString();
    }
}
